iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 9
1

今天的內容比較簡單,準備一些畫面而已,大家可以貼一貼自行看一下就好,或者改造成自己的版本,使用 BootstrapVue 第一步先在 CLI 建好的環境下開啟終端機安裝起來,如果有人不懂 BootstrapVue 的 Layout 方式的話在留言吧! 到時候可能用錄影片的方式來解說討論討論。

npm install bootstrap-vue bootstrap

main.js 加入

import { BootstrapVue } from 'bootstrap-vue'
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'

Vue.use(BootstrapVue)
...
Vue.config.productionTip = false

再分別引入 BootstrapVue 的 JavaScript 和 CSS 檔案後,我們就可以開始在我們的 中使用 BootstrapVue 的元件了。

由於今天要切首頁,先來想想部落格的首頁通常會看到什麼元素

  1. 首頁大圖 Hero image
  2. 導覽列
  3. 文章顯示區
  4. 最近文章顯示區

目前就是先想到這樣,那我們先從第一個首頁大圖開始,由於免費的大圖不易找,所以這邊就隨便塞個標題當作大圖吧,我們先把 App.vue 裡的預設內容全刪了,然後將我們的版面加入以下:

<template>
  <div id="app">
    <b-container fluid class="hero">
      <b-row>
        <b-col cols="12">
          <div class="hero--chooseHero">
            <div class="hero--chooseHero__content">
              <h1>IT幫幫忙 - 鐵人賽 30 天</h1>
              <p>自討苦吃</p>
            </div>
          </div>
        </b-col>
      </b-row>
    </b-container>

    <b-navbar type="dark" variant="dark">

			<!-- 這邊使用 BV 支援 <router-link to=...>的元件 -->
      <b-navbar-nav>
        <b-nav-item to="/">Home</b-nav-item>
        <b-nav-item to="/about">About Me</b-nav-item>
      </b-navbar-nav>

			<!-- 這邊使用 BV navbar 的搜尋框元件,後面用以搜尋文章 -->
      <b-navbar-nav class="ml-auto">
        <b-nav-form>
          <b-form-input size="sm" class="mr-sm-2" placeholder="Search"></b-form-input>
          <b-button size="sm" class="my-2 my-sm-0" type="submit">Search</b-button>
        </b-nav-form>
      </b-navbar-nav>
    </b-navbar>

		<!-- 負責顯示所有內容 -->
    <router-view/>

  </div>
</template>

接著換掉 CSS 的部分在這:

// 加入 scope 表示 CSS 有效範圍僅包含此檔案
<style lang="scss" scope>
* {
  font-family: 微軟正黑體;
  box-sizing: border-box;
}

#app {
  h1,h2,h3,h4,h5,h6,p {
    margin: 0px;
  }

  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  color: #2c3e50;
}

.container-fluid.hero {
  background-color: #024e82;
  .hero--chooseHero {
    position: relative;
    padding: 1rem;
    height: 300px;
    color: #ddd;

    & > .hero--chooseHero__content {
      position: absolute;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
      padding: 3rem;
      border: solid 2px #ddd;
      border-radius: 5px;
      text-align: center;

      & > h1,p {
        user-select: none;
      }
    }
  }
}

nav {
  &.navbar { padding: 1rem; }
  .nav-item {
    a {
      font-weight: bold;
      color: #ccc;
      user-select: none;
    }
    a.router-link-exact-active {
      color: #42b983 !important;
    }
  }
}

</style>

其中我們原本 的部分變成由下面這個取代,這邊是 BV 的 component,可以無痛的和 Router 做結合。

<b-nav-item> is the primary link (and <router-link>) component. Providing a to prop value will generate a <router-link> while providing an href prop value will generate a standard link.

<b-nav-item to="/">Home</b-nav-item>
<b-nav-item to="/about">About Me</b-nav-item>

現在應該得到這樣代表首頁大圖及導航欄的內容

https://ithelp.ithome.com.tw/upload/images/20200917/20129819AhtsDhbdGV.png

再來就要準備我們文章顯示區塊的排版,最常見的就是分左右,左邊是一塊塊綠豆糕,由邊是一堆屑屑。所以接下來開玩笑地,我們就分左右兩塊,左邊區塊就是文章一篇篇往下堆疊,右邊就是負責抓最近的比如說 10 篇文章的區塊,所以左右兩區塊。

現在把 components 資料夾內的 HelloWord.vue 換成 Articles.vue,並把裡面的原先內容通通刪除,我們準備把這邊拿來當作左邊區塊的文章配置。

再新增一個 Recently.vue,準備拿來當作右邊區塊的配置。

https://ithelp.ithome.com.tw/upload/images/20200917/20129819RTQj293fQT.png

先準備 Articles.vue 的內容

<template>
  <div class="article__blocks">
    <div class="article__blocks__block" v-for="article in posts" :key="article.id">
      <div class="article__blocks__block_title">
        <h3>{{ article.title }}</h3>
      </div>
      <div class="article__blocks__block_content">
        <p>{{ article.content }}</p>
      </div>
      <div class="goto">
        <p>>> 繼續閱讀</p>
      </div>
    </div>
  </div>
</template>

我們的 template 中,使用 v-for 來進行文章的渲染,所以我們必須有一個資料區塊負責儲存我們的文章,所以現在我們先來定義我們的文章資料結構,我們定義一個陣列,裡面每個成員都具有文章題目、內容、id,資訊都是可以再擴充的,所以務必讓每篇文章資訊用一個物件包含起來,這樣後續才方便擴充比如說作者阿,文章建立時間阿啥的。:

<script>
export default {
  name: 'Article',
  props: {
    msg: String
  },
  data () {
    return {
      posts: [
        {
          title: '鐵人賽第一天',
          content: '第一天就不知道怎麼辦,還有29天也...',
          id: 12
        }, {
          title: '鐵人賽第一天',
          content: '第一天就不知道怎麼辦,還有29天也...',
          id: 12
        }, {
          title: '鐵人賽第一天',
          content: '第一天就不知道怎麼辦,還有29天也...',
          id: 12
        }, {
          title: '鐵人賽第一天',
          content: '第一天就不知道怎麼辦,還有29天也...',
          id: 12
        }, {
          title: '鐵人賽第一天',
          content: '第一天就不知道怎麼辦,還有29天也...',
          id: 12
        }, {
          title: '鐵人賽第一天',
          content: '第一天就不知道怎麼辦,還有29天也...',
          id: 12
        }, {
          title: '鐵人賽第一天',
          content: '第一天就不知道怎麼辦,還有29天也...',
          id: 12
        }, {
          title: '鐵人賽第一天',
          content: '第一天就不知道怎麼辦,還有29天也...',
          id: 12
        }
      ]
    }
  }
}
</script>

這邊只是先模擬我們的文章內容而已,後面章節我們會改為Call API 的方式動態的取得文章,id 內容是不會像現在這樣重複的。

然後再準備我們的 CSS,大概就好啦,不喜請噴ㄏㄏ。

<style lang="scss" scoped>
.article__blocks {
  padding: 2rem;
  display: grid;
  grid-template-rows: auto;

  & > .article__blocks__block {
    position: relative;
    margin: 2rem;
    border: solid #aaa 1px;
    border-radius: 5px;
    padding: 1rem;
    height: 200px;
    box-shadow: 2px 2px 1px 0px #444;

    &:hover {
      background-color: #ddd;
    }
    & > div {
      user-select: none;
    }

    .article__blocks__block_title {
      margin: .5rem
    }

    .article__blocks__block_content {
      margin: .5rem
    }

    .goto {
      position: absolute;
      right: 5%;
      bottom: 5%;
      cursor: pointer;

      &:hover {
        color: #333;
        border-bottom: 1px solid brown;
      }

      &:active {
        border-bottom: 0;
      }
    }
  }
}
</style>

再來是 Recently.vue 的內容配置,比較少一次全貼。

<template>
  <div class="recentlyArticle">
    <div class="recentlyArticle__content">這邊抓取近期文章</div>
  </div>
</template>

<script>
export default {
  name: 'Recently'
}
</script>

<style lang="scss">
  .recentlyArticle {
    border: solid 1px #444;
    border-radius: 5px;
    padding: 2rem;
    margin-top: 4rem;
    .recentlyArticle__content {
      height: 600px;
    }
  }
</style>

最後要記得把 Recently.vue 的部份引入到我們的 Home 首頁組件,此時首頁組件包含了 Articles.vue 、 Recently.vue 兩個組件。

Home.vue 內
<template>
  <b-container>
    <b-row>
      <b-col cols="9"><Articles/></b-col>
      <b-col cols="3"><Recently/></b-col>
    </b-row>
  </b-container>
</template>

<script>
// @ is an alias to /src
import Articles from '@/components/Articles.vue'
import Recently from '@/components/Recently.vue'

export default {
  name: 'Home',
  components: {
    Articles,
    Recently
  }
}
</script>

<style lang="scss" scoped>
</style>

設定完後,現在我們的畫面暫時長這樣 :

https://ithelp.ithome.com.tw/upload/images/20200917/20129819JW7FCpeBoP.png

現在我們已經有個基本的版面了,因為我們的重點著重於背後功能的邏輯,所以我們版面配置和 CSS 啥地其實都可以自行安排。明天我們會先將此頁擱置,然後這是預計接下來的進度:

  1. 接著介紹 Firebase 的驗證,然後實作一個登入登出功能
  2. 準備後台頁面,實作一個發文功能 ( 登入後才進到後台 )
  3. 回到本頁面,讓我們的頁面動態載入文章

沒事也可以逛逛我們其他團隊成員的文章啦 ~~
eien_zheng: 前端小嘍嘍的Golang學習旅程_The journey of learning Golang 系列
PollyPO技術: 前端設計轉前端工程師-JS踩坑雜記 30 天 系列
阿電: 忍住不打牌位,只要30天VueJS帶你上A牌 系列
喬依司: 實作經典 JavaScript 30 系列


上一篇
Day 08: Vue Router 超基本部分
下一篇
Day 10: Firebase 導讀
系列文
Vue CLI + Firebase 雲端資料庫 30天打造簡易部落格及後臺管理30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言